package org.yanh.es.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.github.houbb.segment.support.segment.result.impl.SegmentResultHandlers;
import com.github.houbb.segment.util.SegmentHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkProcessor;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.*;
import org.yanh.es.domain.Poem;
import org.yanh.es.service.IPoemService;
import org.yanh.es.utils.BulkProcess;
import org.yanh.es.utils.DBHelper;
import org.yanh.es.utils.EsUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/poem")
@RequiredArgsConstructor
public class PoemController {
    //Mysql大批量数据导入ElasticSearch:https://blog.csdn.net/u013850277/article/details/88904303
    //使用logstash实现mysql到ES的数据迁移 https://blog.csdn.net/qq_43361467/article/details/128492705

    private final IPoemService poemService;
    private final RestHighLevelClient client;
    @Autowired
    private EsUtils<Poem> utils;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping ("/findByPage")
    public Map<String, Object> queryItemByPage(Integer page, Integer rows) {
        Map<String, Object> map = new HashMap<>();
        //查询所有诗词 每个诗中包含所属分类
        List<Poem> poems = poemService.findByPage(page, rows);
        //查询古诗总记录数
        Long totalCounts = poemService.findTotalCounts();
        //计算总页数
        Long totalPage = totalCounts % rows == 0 ? totalCounts / rows : totalCounts / rows + 1;
        map.put("page", page);
        map.put("rows", poems);
        map.put("total", totalPage);
        map.put("records", totalCounts);
        return map;
    }

    //获取redis热词排行榜
    @RequestMapping("findRedisKeywords")
    public Set<ZSetOperations.TypedTuple<String>> findRedisKeywords(){
        Set<ZSetOperations.TypedTuple<String>> keywords = stringRedisTemplate.opsForZSet().reverseRangeWithScores("keywords", 0, 20);
        return keywords;
    }

    //前台搜索
    //前台系统根据关键词检索
    @GetMapping("findAllKeywords")//参数1:搜索的条件   参数2:搜索类型  参数3:根据指定作者搜索
    public Map<String, Object> findAll(String content, String type, String author) {
        Map<String, Object> map = new HashMap<>();
        //放入redis
        if (!StringUtils.isEmpty(content)) {
            //对搜索进行分词处理
            List<String> segment = SegmentHelper.segment(content, SegmentResultHandlers.word());
            log.info("当前搜索分词结果为:[{}]",segment);
            segment.forEach(word->{
                if(word.length()>1){
                    stringRedisTemplate.opsForZSet().incrementScore("keywords", word, 0.5);
                }
            });
        }
        if (StringUtils.equals("所有", type)) type = null;
        if (StringUtils.equals("所有", author)) author = null;
        log.info("type:[{}] author:[{}] ", type, author);
        try {
            List<Poem> poems = poemService.findByKeywords(content, type, author);
            map.put("success", true);
            map.put("msg", "查询成功!");
            map.put("poems", poems);
        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", false);
            map.put("msg", "检索出错!");

        }
        return map;
    }

    //批量录入ES索引库
    @RequestMapping("saveAll")
    public Map<String, Object> saveAll() {
        log.info("正在执行索引的创建请稍后....");
        var res=utils.deleteAllByIndices("poems");
        log.info(res+"文档已全部清除!!!");
        Map<String, Object> map = new HashMap<>();
        try {
            writeMysqlDataToES("poems");
            map.put("success", true);
            map.put("msg", "索引录入成功!");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", false);
            map.put("msg", "索引录入失败:" + e.getMessage());
        }
        return map;
    }

    //清空所有文档
    @RequestMapping("deleteAll")
    public Map<String, Object> deleteAll() {
        log.info("正在执行索引的清除....");
        log.warn("正在执行索引的清除....");
        log.error("正在执行索引的清除....");
        Map<String, Object> map = new HashMap<>();
        try {
            var res=utils.deleteAllByIndices("poems");
            map.put("success", true);
            map.put("msg", res+"文档已全部清除!!!");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", false);
            map.put("msg", "文档清除失败:" + e.getMessage());
        }
        return map;
    }

    /**
     * 将mysql 数据查出组装成es需要的map格式，通过批量写入es中
     */
    public void writeMysqlDataToES(String indexName) {
        BulkProcessor bulkProcessor = BulkProcess.getBulkProcessor(client);
        try {
            List<Poem> list=poemService.findAll();
            for(Poem poem : list){
                bulkProcessor.add(new IndexRequest().index(indexName).source(JSON.toJSONString(poem), XContentType.JSON));
            }
            log.info("-------------------------- Finally insert number total : " + list.size());
            // 将数据刷新到es, 注意这一步执行后并不会立即生效，取决于bulkProcessor设置的刷新时间
            bulkProcessor.flush();
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            try {
                boolean terminatedFlag = bulkProcessor.awaitClose(150L, TimeUnit.SECONDS);
                log.info(String.valueOf(terminatedFlag));
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
    }


}
